package com.pan.net;

import com.pan.entity.transmit.Packet;
import com.pan.enumn.MessageEnum;
import com.pan.utils.ErrorLog;

import java.io.*;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;

public class Connection {

    private ServerSocket serverSocket;


    private Socket socket;

    private InetAddress inetAddress;


    public Connection()  {
    }


    public boolean packetEqual(Packet p, MessageEnum e){
        if (p.getCode() == e.getCode()){
            return true;
        }else {
            return false;
        }
    }
    public boolean connect(String host, int port, String password){
        try {
            InetAddress ia = InetAddress.getByName(host);
            Socket s = new Socket(ia,port);
            Packet connectPacket = new Packet<>(MessageEnum.CONNECT,password);
            ObjectOutputStream oos = new ObjectOutputStream(s.getOutputStream());
            oos.writeObject(connectPacket);
            oos.flush();


            ObjectInputStream ois = new ObjectInputStream(s.getInputStream());
            Packet receive = (Packet) ois.readObject();

            if (packetEqual(receive,MessageEnum.SUCCESS)){
                inetAddress = s.getInetAddress();
                this.socket = s;
                return true;
            }else {
                ois.close();
                oos.close();
                s.close();
                return false;
            }
        } catch (Exception e) {

           e.printStackTrace();
            System.out.println(e);
           return false;
        }
    }
    private Thread waitThread;
    //
    public void waitConnect(String password) throws IOException {
        serverSocket = serverSocket==null?new ServerSocket(11451):serverSocket;
        waitThread = new Thread(()->{
            l0:
            while (true){
                try {
                    Socket s = serverSocket.accept();
                    ObjectInputStream ois = new ObjectInputStream(s.getInputStream());
                    Packet<String> receive = (Packet) ois.readObject();
                    ObjectOutputStream oos = new ObjectOutputStream(s.getOutputStream());
                    if (packetEqual(receive,MessageEnum.CONNECT) &&
                            receive.getData().equals(password)){
                        oos.writeObject(new Packet<>(MessageEnum.SUCCESS));
                        this.socket = s;
                        break l0;
                    }else {
                        Packet fail = new Packet<>(MessageEnum.FAIL);
                        oos.writeObject(fail);
                        oos.flush();

                        ois.close();
                        oos.close();
                        s.close();
                        continue l0;
                    }

                } catch (Exception e) {
                    throw new RuntimeException(e);
                }

            }
        });
        waitThread.start();
    }
    public void offWaitConnection(){
        waitThread.interrupt();
        try {
            serverSocket.close();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    private boolean checkFlag = false;
    public boolean checkSocket(){
        checkFlag = true;

        while (checkFlag){
            if (socket != null){
                return true;
            }
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
        return false;
    }
    public void offCheckSocket(){
        checkFlag = false;
    }


    public Socket getSocket() {
        return socket;
    }

    public InetAddress getInetAddress() {
        return inetAddress;
    }


    public void closeSocket(){
        try {
            if (socket != null){
                socket.close();
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }


}
